home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Celestin Apprentice 5
/
Apprentice-Release5.iso
/
Source Code
/
Libraries
/
CW GUSI 1.6.4
/
src
/
GUSIFSp.cp
< prev
next >
Wrap
Text File
|
1995-10-25
|
23KB
|
1,148 lines
/*********************************************************************
Project : GUSI - Grand Unified Socket Interface
File : GUSIFSp.cp - Dealing with paths
Author : Matthias Neeracher <neeri@iis.ethz.ch>
Language : MPW C++
$Log: GUSIFSp.cp,v $
Revision 1.4 1994/12/30 20:00:56 neeri
Add encoded FSSpecs.
Revision 1.3 1994/08/10 00:27:23 neeri
Sanitized for universal headers.
Fixed a deadly bug with multiple nonexistent path components.
Revision 1.2 1994/05/01 23:38:45 neeri
Another rename() fix.
Revision 1.1 1994/03/08 22:06:44 neeri
Initial revision
Revision 0.12 1994/02/04 00:00:00 neeri
Make TFileSpec constructors preserve case to allow above
Revision 0.11 1993/10/24 00:00:00 neeri
Allow changing case in a rename
Revision 0.10 1993/09/27 00:00:00 neeri
FSpSmartMove
Revision 0.9 1993/07/17 00:00:00 neeri
LastInfo
Revision 0.8 1993/06/21 00:00:00 neeri
Throw out the inline
Revision 0.7 1993/03/01 00:00:00 neeri
Bless
Revision 0.6 1993/02/06 00:00:00 neeri
Use FSMakeFSSpec if possible
Revision 0.5 1993/01/15 00:00:00 neeri
IsParentOf
Revision 0.4 1992/11/15 00:00:00 neeri
Rename GUSIFSp_P.h to TFileSpec.h (there we go again)
Revision 0.3 1992/11/15 00:00:00 neeri
Forgot a few consts
Revision 0.2 1992/09/12 00:00:00 neeri
Renamed Paths.h to GUSIFSp_P.h
Revision 0.1 1992/09/06 00:00:00 neeri
Clear ioACUser
*********************************************************************/
#include "GUSI_P.h"
#include "TFileSpec.h"
#include <Errors.h>
#include <Memory.h>
#include <Aliases.h>
#include <Resources.h>
#include <string.h>
#include <errno.h>
#include <TextUtils.h>
#include <PLStringFuncs.h>
#pragma segment GUSI
#define ROOT_MAGIC_COOKIE 666
OSErr TFileSpec::error;
short TFileSpec::curVol;
long TFileSpec::curDir = -1;
CInfoPBRec TFileSpec::lastInfo;
OSErr TFileSpec::ChDir(const TFileSpec & spec)
{
TFileSpec nudir(spec);
nudir += (StringPtr) "\p";
if (error)
return error;
curVol = nudir.vRefNum;
curDir = nudir.parID;
return noErr;
}
static OSErr CurrentDir(short & vRefNum, long & parID)
{
OSErr error;
WDPBRec vol;
Str63 name;
vol.ioNamePtr = name;
if (error = PBHGetVolSync(&vol))
return error;
vRefNum = vol.ioWDVRefNum;
parID = vol.ioWDDirID;
return noErr;
}
OSErr TFileSpec::DefaultDir()
{
if (curDir != -1) {
vRefNum = curVol;
parID = curDir;
return noErr;
} else
return error = CurrentDir(vRefNum, parID);
}
OSErr TFileSpec::FindVol(short index)
{
if (name[0] || index>0) {
ParamBlockRec vol;
vol.volumeParam.ioNamePtr = name;
vol.volumeParam.ioVolIndex = index;
if (error = PBGetVInfoSync(&vol))
return error;
vRefNum = vol.volumeParam.ioVRefNum;
} else {
error = noErr;
vRefNum = 0;
}
parID = fsRtParID;
return error;
}
void TFileSpec::Root()
{
vRefNum = ROOT_MAGIC_COOKIE;
parID = 0;
name[0] = 0;
error = noErr;
}
Boolean TFileSpec::IsRoot()
{
return (!parID && vRefNum == ROOT_MAGIC_COOKIE);
}
OSErr TFileSpec::Default()
{
if (!DefaultDir())
--*this;
return error;
}
TFileSpec::TFileSpec(const TFileSpec & spec)
{
vRefNum = spec.vRefNum;
parID = spec.parID;
if (spec.name[0] < 64)
PLstrcpy(name, spec.name);
else
memcpy(name, spec.name, 64);
}
TFileSpec::TFileSpec(const FSSpec & spec, Boolean useAlias)
{
vRefNum = spec.vRefNum;
parID = spec.parID;
if (spec.name[0] < 64)
PLstrcpy(name, spec.name);
else
memcpy(name, spec.name, 64);
if (!useAlias && hasAlias)
Resolve();
}
TFileSpec::TFileSpec(short vRefNum, long parID, ConstStr31Param name, Boolean useAlias)
{
OSErr err;
if (!hasMakeFSSpec ||
((err = FSMakeFSSpec(vRefNum, parID, name, this)) && (err != fnfErr))
) {
this->vRefNum = vRefNum;
this->parID = parID;
memcpy(this->name, name, *name+1);
}
if (!useAlias && hasAlias)
Resolve();
if (EqualString(this->name, name, false, true))
memcpy(this->name, name, *name+1);
}
TFileSpec::TFileSpec(short wd, ConstStr31Param name, Boolean useAlias)
{
OSErr err;
if (!hasMakeFSSpec ||
((err = FSMakeFSSpec(wd, 0, name, this)) && (err != fnfErr))
) {
WDPBRec wdPB;
wdPB.ioNamePtr = nil;
wdPB.ioVRefNum = wd;
wdPB.ioWDIndex = 0;
wdPB.ioWDProcID = 0;
/* Change the Working Directory number in vRefnum into a real vRefnum */
/* and DirID. The real vRefnum is returned in ioVRefnum, and the real */
/* DirID is returned in ioWDDirID. */
if (error = PBGetWDInfoSync(&wdPB))
return;
vRefNum = wdPB.ioWDVRefNum;
parID = wdPB.ioWDDirID;
memcpy(this->name, name, *name+1);
}
if (!useAlias && hasAlias)
Resolve();
if (EqualString(this->name, name, false, true))
memcpy(this->name, name, *name+1);
}
TFileSpec::TFileSpec(OSType object, short vol, long dir)
{
if (object == kTempFileType && dir) {
vRefNum = vol;
parID = dir;
} else if (
error =
FindFolder(
vol, (object == kTempFileType) ? kTemporaryFolderType : object,
true, &vRefNum, &parID)
)
return;
if (object == kTempFileType) {
static long nr = -1;
PLstrcpy(name, (StringPtr) "\ptmp00000");
do {
nr = (nr + 1) % 100000;
sprintf((char *) name+4, "%05ld", nr);
} while (Exists());
} else {
*this -= 1;
}
}
TFileSpec::TFileSpec(short fRefNum)
{
FCBPBRec fcb;
Str255 fname;
fcb.ioNamePtr = name;
fcb.ioRefNum = fRefNum;
fcb.ioFCBIndx = 0;
if (error = PBGetFCBInfoSync(&fcb))
return;
vRefNum = fcb.ioFCBVRefNum;
parID = fcb.ioFCBParID;
}
void TFileSpec::Bless()
{
if (hasMakeFSSpec) {
FSSpec spec = *this; // Dont know what happens to an aliased name
error = FSMakeFSSpec(spec.vRefNum, spec.parID, spec.name, this);
if (EqualString(spec.name, name, false, true))
memcpy(name, spec.name, *spec.name+1);
} else
error = noErr;
}
#define maxPathLen 512
static char fullPath[maxPathLen];
/* Prefix a path name component to path and update path */
static void CopyComponent(char *& path, const unsigned char * component, Boolean colon)
{
if (colon)
*--path = ':';
path -= *component;
memmove(path, component+1, *component);
}
/* Convert an FSSpec into a full pathname. The pathname is accumulated on the
high end of path to avoid excessive copying.
*/
char * TFileSpec::FullPath() const
{
char * curPath = fullPath + maxPathLen - 1;
StringPtr scratch = (StringPtr) fullPath;
*curPath = 0;
CopyComponent(curPath, name, parID == fsRtParID);
lastInfo.dirInfo.ioNamePtr = scratch;
for (
lastInfo.dirInfo.ioDrParID = parID;
lastInfo.dirInfo.ioDrParID != fsRtParID;
) {
lastInfo.dirInfo.ioVRefNum = vRefNum;
lastInfo.dirInfo.ioFDirIndex = -1;
lastInfo.dirInfo.ioDrDirID = lastInfo.dirInfo.ioDrParID;
if (error = PBGetCatInfoSync(&lastInfo))
return "";
CopyComponent(curPath, scratch, true);
}
return curPath;
}
char * TFileSpec::FullAliasPath() const
{
char * curPath = fullPath + maxPathLen - 1;
StringPtr scratch = (StringPtr) fullPath;
*curPath = 0;
CInfoPBRec info;
if (error = CatInfo(info))
return nil;
if (!hasAlias || !IsAlias(info)) {
error = resFNotFound; // Close enough for Government work
return nil;
}
short oldRes = CurResFile();
short res = FSpOpenResFile(this, fsRdPerm);
AliasHandle alias;
if (res == -1) {
error = ResError();
alias = nil;
} else {
if (alias = (AliasHandle) Get1Resource('alis', 0))
DetachResource((Handle) alias);
else
error = ResError();
CloseResFile(res);
}
UseResFile(oldRes);
if (!alias)
return nil;
/*
Build path from target up to root. Separate with colons.
*/
for (short index = 0; !(error = GetAliasInfo(alias, index, scratch)); ++index)
if (*fullPath)
CopyComponent(curPath, scratch, index != 0);
else
break;
if (!error && !(error = GetAliasInfo(alias, asiVolumeName, scratch)))
CopyComponent(curPath, scratch, true);
DisposeHandle((Handle) alias);
return error ? nil : curPath;
}
char * TFileSpec::RelPath() const
{
short curVRef;
long curDirID;
if (CurrentDir(curVRef, curDirID))
return FullPath();
else
return RelPath(curVRef, curDirID);
}
char * TFileSpec::RelPath(const FSSpec & dir) const
{
TFileSpec directory(dir);
if (directory.Error())
return FullPath();
++directory;
if (directory.Error())
return FullPath();
else
return RelPath(directory.vRefNum, directory.parID);
}
char * TFileSpec::RelPath(short curVRef, long curDirID) const
{
char * curPath;
/* Special case: a volume was specified */
if (parID == fsRtParID) {
if (vRefNum == curVRef && curDirID == fsRtDirID)
curPath = fullPath;
else {
memcpy(fullPath, name+1, *name);
curPath = fullPath+*name;
}
curPath[0] = ':';
curPath[1] = 0;
return fullPath;
}
lastInfo.dirInfo.ioNamePtr = (StringPtr)fullPath;
lastInfo.dirInfo.ioVRefNum = curVRef;
lastInfo.dirInfo.ioFDirIndex = -1;
lastInfo.dirInfo.ioDrDirID = curDirID;
if (error = PBGetCatInfoSync(&lastInfo))
return "";
if (curVRef == vRefNum
&& lastInfo.dirInfo.ioDrParID == parID
&& !memcmp (fullPath, name, *fullPath+1)
) {
fullPath[0] = ':';
fullPath[1] = 0;
return fullPath;
}
fullPath[maxPathLen-1] = 0;
curPath = fullPath+maxPathLen-*name-1;
memcpy(curPath, name+1, *name);
lastInfo.dirInfo.ioNamePtr = (StringPtr) fullPath;
lastInfo.dirInfo.ioDrParID = parID;
do {
*--curPath = ':';
/* Test fur current directory */
if (curVRef == vRefNum && curDirID == lastInfo.dirInfo.ioDrParID)
return strchr(curPath+1, ':') ? curPath : curPath+1;
lastInfo.dirInfo.ioVRefNum = vRefNum;
lastInfo.dirInfo.ioFDirIndex = -1;
lastInfo.dirInfo.ioDrDirID = lastInfo.dirInfo.ioDrParID;
if (error = PBGetCatInfoSync(&lastInfo))
return "";
curPath -= *fullPath;
memmove(curPath, fullPath+1, *fullPath);
} while (lastInfo.dirInfo.ioDrDirID != fsRtDirID);
return curPath;
}
// Give encoded path. Encoding is:
//
// 1 byte: DC1 (ASCII 0x11)
// 4 bytes: Volume reference number in zero-padded hex
// 8 bytes: Directory ID in zero-padded hex
// n bytes: Partial pathname, starting with ':'
//
// Needless to say, passing encoded values to anything but a GUSI routine is
// a bad idea.
char * TFileSpec::Encode() const
{
sprintf(fullPath, "\021%04hX%08X:", vRefNum, parID);
memcpy(fullPath + 14, name+1, name[0]);
fullPath[14+name[0]] = 0;
return fullPath;
}
OSErr TFileSpec::CatInfo(CInfoPBRec & info, Boolean dirInfo) const
{
info.dirInfo.ioVRefNum = vRefNum;
info.dirInfo.ioDrDirID = parID;
info.dirInfo.ioNamePtr = (StringPtr) name;
info.dirInfo.ioFDirIndex = dirInfo ? -1 : 0;
info.dirInfo.ioACUser = 0;
return error = PBGetCatInfoSync(&info);
}
TFileSpec TFileSpec::operator--()
{
if (parID == fsRtParID)
Root();
else {
CatInfo(lastInfo, true);
if (!error)
parID = lastInfo.dirInfo.ioDrParID;
}
return *this;
}
TFileSpec TFileSpec::operator++()
{
if (IsRoot()) {
vRefNum = 0;
parID = fsRtParID;
name[0] = 0;
goto punt;
}
if (CatInfo(lastInfo))
goto punt;
// Resolve if an alias
if (IsAlias(lastInfo))
if (Resolve(lastInfo) || CatInfo(lastInfo))
goto punt;
if (IsFile(lastInfo)) {
error = afpObjectTypeErr;
goto punt;
}
parID = lastInfo.dirInfo.ioDrDirID;
punt:
return *this;
}
TFileSpec TFileSpec::operator-=(int levels)
{
while (levels-- > 0) {
--*this;
if (this->Error())
break;
}
return *this;
}
TFileSpec TFileSpec::operator-(int levels) const
{
TFileSpec spec = *this;
return spec -= levels;
}
OSErr TFileSpec::Resolve(const CInfoPBRec & info)
{
Boolean isFolder;
Boolean wasAlias;
return error =
(hasAlias && IsAlias(info)) ?
ResolveAliasFile(this, true, &isFolder, &wasAlias) :
noErr;
}
OSErr TFileSpec::Resolve(Boolean gently)
{
CatInfo(lastInfo);
if (error)
if (gently)
return error = noErr;
else
return error;
else
return Resolve(lastInfo);
}
Boolean TFileSpec::Exists() const
{
Boolean res;
res = !CatInfo(lastInfo);
error = noErr;
return res;
}
Boolean TFileSpec::operator==(const TFileSpec & other) const
{
return vRefNum == other.vRefNum
&& parID == other.parID
&& EqualString(name, other.name, false, true);
}
Boolean TFileSpec::operator!=(const TFileSpec & other) const
{
return vRefNum != other.vRefNum
|| parID != other.parID
|| !EqualString(name, other.name, false, true);
}
Boolean TFileSpec::IsParentOf(const TFileSpec & other) const
{
for (TFileSpec oth = other - 1; !oth.Error() && *this != oth; --oth)
if (oth == *this)
return true;
return false;
}
TFileSpec TFileSpec::AddPathComponent(const char * name, int length)
{
if (length > 63) {
error = bdNamErr;
goto punt;
}
++(*this);
if (error)
goto punt;
memcpy(this->name+1, name, *this->name = length);
if (parID == fsRtParID)
FindVol(-1);
punt:
return *this;
}
TFileSpec TFileSpec::operator+=(ConstStr31Param name)
{
return AddPathComponent((const char *) name+1, *name);
}
TFileSpec TFileSpec::operator+(ConstStr31Param name) const
{
TFileSpec spec = *this;
return spec += name;
}
TFileSpec TFileSpec::operator+=(const char * name)
{
return AddPathComponent(name, strlen(name));
}
TFileSpec TFileSpec::operator+(const char * name) const
{
TFileSpec spec = *this;
return spec += name;
}
TFileSpec TFileSpec::operator[](short index) const
{
TFileSpec spec = *this;
if (spec.parID == fsRtParID)
spec.FindVol(index);
else {
lastInfo.dirInfo.ioVRefNum = spec.vRefNum;
lastInfo.dirInfo.ioDrDirID = spec.parID;
lastInfo.dirInfo.ioNamePtr = spec.name;
lastInfo.dirInfo.ioFDirIndex = index;
error = PBGetCatInfoSync(&lastInfo);
}
return spec;
}
static Boolean ReadNHex(const char * nr, int count, unsigned long * val)
{
for (*val = 0; count--; ++nr) {
*val <<= 4;
switch (*nr) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
*val |= *nr - '0';
break;
case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
*val |= *nr - 'a' + 10;
break;
case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
*val |= *nr - 'A' + 10;
break;
default:
return false;
}
}
return true;
}
Boolean TFileSpec::IsEncodedFSSpec(const char * path, Boolean useAlias)
{
// To be as robust as possible against conflicts, we won't tolerate any
// deviations from the pattern:
// 1 byte: DC1 (ASCII 0x11)
// 4 bytes: Volume reference number in zero-padded hex
// 8 bytes: Directory ID in zero-padded hex
// n bytes: Partial pathname, starting with ':'
if (*path++ != 0x11) // Magic character DC1
return false;
unsigned long val;
if (ReadNHex(path, 4, &val)) {
vRefNum = short(val);
if (ReadNHex(path+4, 8, &val)) {
parID = long(val);
path += 12;
if (*path == ':' && !strchr(path+1, ':'))
if (!path[1]) {
--(*this);
return true;
} else {
*(char *)path = strlen(path+1);
if (hasMakeFSSpec) {
if (error = FSMakeFSSpec(vRefNum, parID, (ConstStr255Param) path, this))
if (error == fnfErr)
error = noErr;
} else {
this->vRefNum = vRefNum;
this->parID = parID;
memcpy(this->name, path, *path+1);
}
if (!useAlias && hasAlias)
Resolve();
if (EqualString(this->name, (ConstStr255Param) path, false, true))
memcpy(this->name, path, *path+1);
*(char *)path = ':';
return true;
}
}
}
return false;
}
TFileSpec::TFileSpec(const char * path, Boolean useAlias)
{
if (IsEncodedFSSpec(path, useAlias))
return;
int pathLen = int(strlen(path));
StringPtr name = (StringPtr) fullPath;
char * nextPath;
if (hasMakeFSSpec) {
DefaultDir();
CopyC2PStr(path, name);
switch (error = FSMakeFSSpec(vRefNum, parID, name, this)) {
case fnfErr:
error = noErr;
return;
case noErr:
if (!useAlias && hasAlias)
Resolve();
if (nextPath = (char *) strrchr(path, ':'))
path = nextPath+1;
CopyC2PStr(path, name);
if (EqualString(this->name, name, false, true))
memcpy(this->name, name, *name+1);
return;
default:
break;
}
}
if (path[0] == ':' || !(nextPath = (char *) strchr(path, ':'))) {
Default();
if (*path == ':')
++path;
} else {
if (nextPath - (char *) path > 62) {
error = bdNamErr;
return;
}
memcpy(name+1, (char *) path, *name = nextPath - (char *) path + 1);
if (FindVol(-1))
return;
path = nextPath + 1;
}
if (error)
return;
while (*path) {
if (*path == ':') {
--*this;
++path;
if (error)
return;
else
continue;
}
if (nextPath = (char *) strchr(path, ':'))
*nextPath = 0;
*this += path;
if (nextPath)
*nextPath = ':';
if (error)
return;
if (nextPath)
path = nextPath + 1;
else
break;
}
if (!useAlias && hasAlias)
Resolve();
}
/* Convert a FSSpec into a full pathname. */
char * FSp2FullPath(const FSSpec * desc)
{
TFileSpec spec(*desc);
return spec.FullPath();
}
/* Convert a FSSpec into a relative pathname. */
char * FSp2RelPath(const FSSpec * desc)
{
TFileSpec spec(*desc);
return spec.RelPath();
}
/* Works like FSp2RelPath, but regarding to a specified directory.
*/
char * FSp2DirRelPath(const FSSpec * desc, const FSSpec * dir)
{
TFileSpec spec(*desc);
return spec.RelPath(*dir);
}
/* Encode a FSSpec*/
char * FSp2Encoding(const FSSpec * desc)
{
TFileSpec spec(*desc);
return spec.Encode();
}
/* Convert a working directory & file name into a FSSpec. */
OSErr WD2FSSpec(short wd, ConstStr31Param name, FSSpec * desc)
{
TFileSpec spec(wd, name);
*desc = spec;
return spec.Error();
}
/* Convert a pathname into a file spec. */
OSErr Path2FSSpec(const char * path, FSSpec * desc)
{
TFileSpec spec(path);
*desc = spec;
return spec.Error();
}
/* Convert a working directory & file name into a FSSpec. */
OSErr Special2FSSpec(OSType object, short vol, long dirID, FSSpec * desc)
{
TFileSpec spec(object, vol, dirID);
*desc = spec;
return spec.Error();
}
/* Return FSSpec of (vRefNum, parID) */
OSErr FSpUp(FSSpec * desc)
{
TFileSpec spec(*desc);
*desc = --spec;
return spec.Error();
}
/* Return FSSpec of file in directory denoted by desc */
OSErr FSpDown(FSSpec * desc, ConstStr31Param name)
{
TFileSpec spec(*desc);
*desc = spec + name;
return spec.Error();
}
/* Call GetCatInfo for file system object. */
OSErr FSpCatInfo(const FSSpec * desc, CInfoPBRec * info)
{
OSErr err;
TFileSpec spec(*desc);
if (err = spec.CatInfo(*info))
return err;
info->hFileInfo.ioNamePtr = (StringPtr) desc->name;
return noErr;
}
/* Return FSSpec of nth file in directory denoted by (vRefNum, parID) */
OSErr FSpIndex(FSSpec * desc, short n)
{
TFileSpec spec(*desc);
*desc = spec[n];
return spec.Error();
}
static OSErr DefaultVRef(short & vRef)
{
OSErr err;
ParamBlockRec vol;
vol.volumeParam.ioNamePtr = nil;
if (err = PBGetVolSync(&vol))
return err;
vRef = vol.volumeParam.ioVRefNum;
return noErr;
}
OSErr FSpSmartMove(const FSSpec * from, const FSSpec * to)
{
OSErr err;
TFileSpec fromspec(*from, true);
TFileSpec tospec(*to, true);
TFileSpec toparent = tospec - 1;
TFileSpec corner;
CInfoPBRec fromInfo;
CInfoPBRec toInfo;
if (!fromspec.vRefNum)
if (err = DefaultVRef(fromspec.vRefNum))
return err;
if (!tospec.vRefNum)
if (err = DefaultVRef(tospec.vRefNum))
return err;
if (fromspec.vRefNum != tospec.vRefNum)
return diffVolErr;
Boolean diffname = !EqualString(fromspec.name, tospec.name, false, true);
Boolean diffdir = fromspec.parID != tospec.parID;
Boolean toexists = !tospec.CatInfo(toInfo);
Boolean lockfrom;
Boolean lockto;
TFileSpec tmpto;
if (err = fromspec.CatInfo(fromInfo))
return err;
if (!IsFile(fromInfo) && fromspec.IsParentOf(tospec))
return badMovErr;
if (lockfrom = IsFile(fromInfo) && fromInfo.hFileInfo.ioFlAttrib & 0x01)
HRstFLock(fromspec.vRefNum, fromspec.parID, fromspec.name);
if (!diffname && !diffdir) { /* Files are identical, except possibly for case */
err = noErr;
goto cleanupcase;
}
if (toexists)
if (!IsFile(toInfo) && toInfo.dirInfo.ioDrNmFls)
return fBsyErr;
else {
tmpto = TFileSpec(kTempFileType, tospec.vRefNum, tospec.parID);
if (lockto = IsFile(toInfo) && toInfo.hFileInfo.ioFlAttrib & 0x01)
HRstFLock(tospec.vRefNum, tospec.parID, tospec.name);
if (err = HRename(tospec.vRefNum, tospec.parID, tospec.name, tmpto.name))
return err;
}
if (!diffdir) {
err = HRename(fromspec.vRefNum, fromspec.parID, fromspec.name, tospec.name);
goto cleanuptmp;
} else if (!diffname) {
err =
CatMove(
fromspec.vRefNum, fromspec.parID, fromspec.name,
toparent.parID, toparent.name);
goto cleanuptmp;
}
corner = TFileSpec(fromspec.vRefNum, fromspec.parID, tospec.name);
if (!corner.Exists()) {
err = HRename(fromspec.vRefNum, fromspec.parID, fromspec.name, tospec.name);
if (!err)
if (err =
CatMove(
fromspec.vRefNum, fromspec.parID, tospec.name,
toparent.parID, toparent.name)
)
HRename(fromspec.vRefNum, fromspec.parID, tospec.name, fromspec.name);
goto cleanuptmp;
}
{
TFileSpec secondcorner(kTempFileType, tospec.vRefNum, tospec.parID);
memcpy(corner.name, secondcorner.name, secondcorner.name[0]+1);
while (corner.Exists() || secondcorner.Exists()) {
TFileSpec newcorner(kTempFileType, secondcorner.vRefNum, secondcorner.parID);
memcpy(corner.name, newcorner.name, newcorner.name[0]+1);
memcpy(secondcorner.name, newcorner.name, newcorner.name[0]+1);
}
}
err = HRename(fromspec.vRefNum, fromspec.parID, fromspec.name, corner.name);
if (!err)
if (err =
CatMove(
fromspec.vRefNum, fromspec.parID, corner.name,
toparent.parID, toparent.name)
)
HRename(fromspec.vRefNum, fromspec.parID, corner.name, fromspec.name);
else if (err =
HRename(tospec.vRefNum, tospec.parID, corner.name, tospec.name)
) {
TFileSpec fromparent = fromspec - 1;
CatMove(
tospec.vRefNum, tospec.parID, corner.name,
fromparent.parID, fromparent.name);
HRename(fromspec.vRefNum, fromspec.parID, corner.name, fromspec.name);
}
cleanuptmp:
if (toexists)
if (err) {
HRename(tmpto.vRefNum, tmpto.parID, tmpto.name, tospec.name);
if (lockto)
HSetFLock(tospec.vRefNum, tospec.parID, tospec.name);
} else
HDelete(tmpto.vRefNum, tmpto.parID, tmpto.name);
cleanupcase:
if (!err && !diffname)
err = HRename(tospec.vRefNum, tospec.parID, tospec.name, tospec.name);
if (lockfrom)
if (err)
HSetFLock(fromspec.vRefNum, fromspec.parID, fromspec.name);
else
HSetFLock(tospec.vRefNum, tospec.parID, tospec.name);
return err;
}